package com.openess.bigsearch.engine.BTree.util;

public class ByteArrays {
	/**
	 * 拿到数组中指定位置，指定长度的子数组
	 * 
	 * @param src
	 *            源数组
	 * @param srcPos
	 *            源数组截取的起始位置
	 * @param length
	 *            截取长度
	 * @return 子数组
	 */
	public static byte[] get(byte[] src, int srcPos, int length) {
		byte[] result = new byte[length];
		System.arraycopy(src, srcPos, result, 0,
				Math.min(src.length - srcPos, length));
		return result;
	}

	/**
	 * 为了防止最高位为1，返回现实负数，因此最后返回时将byte转换为int表示
	 * 
	 * @param src
	 * @param srcPos
	 * @return
	 */
	public static int getByte(byte[] src, int srcPos) {
		byte[] results = get(src, srcPos, 1);
		int result = results[0] & 0xFF;
		return result;
	}

	/**
	 * 从字节数组中读取一个整数
	 * 
	 * @param src
	 *            源数组
	 * @param srcPos
	 *            源数组读取的起始位置
	 * @param length
	 *            读取多少个字节
	 * @return 读取到的整数
	 */
	public static int getInt(byte[] src, int srcPos) {
		byte[] results = get(src, srcPos, 4);
		int result = 0;
		for (int i = 0; i < 4; i++) {
			result |= (results[i] & 0xFF) << (24 - 8 * i);
		}
		return result;
	}

	public static double getDouble(byte[] src, int srcPos) {
		return Double.longBitsToDouble(getLong(src, srcPos));
	}

	public static float getFloat(byte[] src, int srcPos) {
		return Float.intBitsToFloat(getInt(src, srcPos));
	}

	public static short getShort(byte[] src, int srcPos) {
		byte[] results = get(src, srcPos, 2);
		short result = 0;
		for (int i = 0; i < 2; i++) {
			result |= (results[i] & 0xFF) << (8 - 8 * i);
		}
		return result;
	}

	public static long getLong(byte[] src, int srcPos) {
		byte[] results = get(src, srcPos, 8);
		long result = 0;
		for (int i = 0; i < 8; i++) {
			result |= ((long) results[i] & 0xFF) << (56 - 8 * i);
		}
		return result;
	}

	/**
	 * 读取字符，putString里面已经保存了字符长度，但这里还要求输入字符长度是因为ByteBuffer读取的时候需要先指定字节数，
	 * 所以必须先把字符长度拿到
	 * 
	 * @param src
	 * @param srcPos
	 * @param length
	 * @return
	 */
	public static String getString(byte[] src, int srcPos, int length) {
		char[] chars = new char[length];
		for (int i = 0; i < length; i++) {
			chars[i] = getChar(src, srcPos + i * 2);
		}
		return String.valueOf(chars);
	}

	public static char getChar(byte[] src, int srcPos) {
		byte[] results = get(src, srcPos, 2);
		char result = 0;
		for (int i = 0; i < 2; i++) {
			result |= (results[i] & 0xFF) << (8 - 8 * i);
		}
		return result;
	}

	public static boolean getBoolean(byte[] src, int srcPos) {
		byte b = src[srcPos];
		return b == (byte) 0x01 ? true : false;
	}

	/**
	 * 清除数组的指定数据
	 * 
	 * @param src
	 *            源数组
	 * @param srcPos
	 *            清除的起始位置
	 * @param length
	 *            清除的长度
	 */
	public static void clear(byte[] src, int srcPos, int length) {
		byte[] temp = new byte[length];
		System.arraycopy(temp, 0, src, srcPos, length);
	}

	public static void put(byte[] src, int srcPos, byte[] dest, int destPos,
			int length) {
		System.arraycopy(src, srcPos, dest, destPos,
				Math.min(src.length - srcPos, length));
	}

	public static void putByte(byte src, byte[] dest, int destPos) {
		dest[destPos] = (byte) (src & 0xFF);
	}

	public static void putInt(int src, byte[] dest, int destPos) {
		for (int i = 0; i < 4; i++) {
			dest[destPos + i] = (byte) ((src >>> (24 - 8 * i)) & 0xFF);
		}
	}

	public static void putDouble(double src, byte[] dest, int destPos) {
		putLong(Double.doubleToLongBits(src), dest, destPos);
	}

	public static void putFloat(float src, byte[] dest, int destPos) {
		putInt(Float.floatToIntBits(src), dest, destPos);
	}

	public static void putShort(short src, byte[] dest, int destPos) {
		for (int i = 0; i < 2; i++) {
			dest[destPos + i] = (byte) ((src >>> (8 - 8 * i)) & 0xFF);
		}
	}

	public static void putLong(long src, byte[] dest, int destPos) {
		for (int i = 0; i < 8; i++) {
			dest[destPos + i] = (byte) ((src >>> (56 - 8 * i)) & 0xFF);
		}
	}

	public static void putChars(String str, byte[] dest, int destPos) {
		for (int i = 0; i < str.length(); i++) {
			char ch = str.charAt(i);
			putChar(ch, dest, destPos + i * 2);
		}
	}

	public static void putChar(char v, byte[] dest, int destPos) {
		byte v1 = (byte) ((v >>> 8) & 0xFF);
		byte v2 = (byte) (v & 0xFF);
		dest[0 + destPos] = v1;
		dest[1 + destPos] = v2;
	}

	/**
	 * java中没有具体说明boolean占多少位，因此true假设为1，false假设为0，用一个byte进行保存
	 * 
	 * @param b
	 * @param dest
	 * @param desPos
	 */
	public static void putBoolean(boolean b, byte[] dest, int desPos) {
		dest[desPos] = b ? (byte) 0x01 : 0x00;
	}

	/**
	 * 保存字符串,前两个字节用于保存字符串的长度
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] putString(String str) {
		// 前两个字节用于保存str的长度，类型short
		byte[] dest = new byte[2 + str.length() * 2];
		putShort((short) str.length(), dest, 0);
		putChars(str, dest, 2);
		return dest;
	}

	/**
	 * 将字符串保存在提前准备好的数组中，保存内容包括了字符串长度
	 * 
	 * @param str
	 * @param dest
	 * @param desPos
	 */
	public static void putString(String str, byte[] dest, int desPos) {
		putShort((short) str.length(), dest, desPos);
		putChars(str, dest, desPos + 2);
	}

	/**
	 * 将数组中的数据进行挪位
	 * 
	 * @param src
	 *            源数组
	 * @param srcPos
	 *            从哪开始移动
	 * @param destPos
	 *            移动到哪
	 */
	public static void move(byte[] src, int srcPos, int destPos, int length) {
		System.arraycopy(src, srcPos, src, destPos, length);
	}
}
